package com.abigdreamer.arkflow;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import net.sf.json.JSONObject;
import net.sf.json.xml.XMLSerializer;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.cat.util.TwoTuple;

public class WorkflowDefineAnalyzer {

	private String convertToXml(String jsonStr) {
		JSONObject json = JSONObject.fromObject(jsonStr);
		XMLSerializer serializer = new XMLSerializer();
		serializer.setTypeHintsEnabled(false);
		serializer.setRootName("root");

		String xml = serializer.write(json);
		return JsonToXML.prettyFormat(xml, 4);
	}

	public TwoTuple<List<WorkflowNode>, WorkflowNode> execute(String jsonStr) {

		String xml = convertToXml(jsonStr);

		Document document = null;
		try {
			document = DocumentHelper.parseText(xml);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		Element roots = document.getRootElement();

		HashMap<String, List<WorkflowPath>> mapPaths = null;
		List<WorkflowNode> states = null;
		WorkflowNode workflow = null;
		for (Object element : roots.elements()) {
			Element node = (Element) element;
			if (node.getName().equals("paths")) {
				mapPaths = analysisPaths(node);
			} else if (node.getName().equals("states")) {
				states = analysisStates(node);
			} else if (node.getName().equals("props")) {
				workflow = analysisProps(node);
			}
		}

		for (WorkflowNode process : states) {
			Iterator<Entry<String, List<WorkflowPath>>> iterPath = mapPaths.entrySet().iterator();
			while (iterPath.hasNext()) {
				Entry<String, List<WorkflowPath>> entryPath = iterPath.next();
				String Pathkey = entryPath.getKey();
				List<WorkflowPath> paths = entryPath.getValue();
				if (process.getProcessName().equals(Pathkey)) {
					process.setPaths(paths);
					break;
				}
			}
		}

		return new TwoTuple<List<WorkflowNode>, WorkflowNode>(states, workflow);
	}

	private WorkflowNode analysisProps(Element node) {
		WorkflowNode workflow = new WorkflowNode();
		// 流程信息
		for (Object temp : node.elements()) {
			Element rect = (Element) temp;
			for (Object childTemp : rect.elements()) {
				Element subnode = (Element) childTemp;
				if (subnode.getName().equals("name")) {
					for (Object nameTemp : subnode.elements()) {
						Element subsubNode = (Element) nameTemp;
						if (subsubNode.getName().equals("value")) {
							workflow.setName(subsubNode.getText());
							break;
						}
						break;
					}
					
				} 
			}
		}
		return workflow;
	}

	private WorkflowNode analysisState(Element rect) {
		WorkflowNode state = new WorkflowNode();
		state.setProcessName(rect.getName());

		for (Object attrElement : rect.elements()) {
			Element subnode = (Element) attrElement;
			if (subnode.getName().equals("type")) {// type
				state.setType(subnode.getText());
			} else if (subnode.getName().equals("text")) {// text
				for (Object temp : subnode.elements()) {
					Element subsubNode = (Element) temp;
					if (subsubNode.getName().equals("text")) {
						state.setName(subsubNode.getText());
						break;
					}
				}
			} else if (subnode.getName().equals("attr")) {// attr
				String location_x = "", location_y = "", width = "", height = "", g = "";
				for (Object childTemp : subnode.elements()) {
					Element subsubNode = (Element) childTemp;
					if (subsubNode.getName().equals("x")) {// x
						location_x = subsubNode.getText();
					} else if (subsubNode.getName().equals("y")) {// y
						location_y = subsubNode.getText();
					} else if (subsubNode.getName().equals("width")) { // width
						width = subsubNode.getText();
					} else if (subsubNode.getName().equals("height")) {// height
						height = subsubNode.getText();
					}
				}
				if (!width.equals("")) {
					g = location_x + "," + location_y + "," + width + "," + height;
				} else {
					g = location_x + "," + location_y;
				}
				state.setG(g);
			} else if(subnode.getName().equals("props")) {// props
				for(Object childTemp:subnode.elements()) {
					Element subsubNode = (Element)childTemp;
					 if (subsubNode.getName().equals("form")) {
						state.setForm(subsubNode.getText());
					} else if (subsubNode.getName().equals("assignType")) {
						state.setAssignType(subsubNode.getText());
					}else if (subsubNode.getName().equals("assigneeValue")) {
						state.setAssignValue(subsubNode.getText());
					}else if (subsubNode.getName().equals("assignee")) {
						state.setAssignee(subsubNode.getText());
					} else if (subsubNode.getName().equals("expr")) {
						state.setExpr(subsubNode.getText());
					}
				}
			}
		}

		return state;
	}

	private List<WorkflowNode> analysisStates(Element node) {

		List<WorkflowNode> states = new ArrayList<WorkflowNode>();

		// 节点
		for (Object element : node.elements()) {
			Element rect = (Element) element;

			WorkflowNode state = analysisState(rect);

			states.add(state);
		}

		return states;
	}

	private WorkflowPath analysisPath(Element rect) {

		WorkflowPath path = new WorkflowPath();
		path.setName(rect.getText());
		String location_x = "", location_y = "", loaction_dot_x = "", location_dot_y = "";
		for (Object pathElement : rect.elements()) {
			Element subnode = (Element) pathElement;
			if (subnode.getName().equals("from")) {// from
				path.setFrom(subnode.getText());
			} else if (subnode.getName().equals("to")) {// to
				path.setTo(subnode.getText());
			} else if (subnode.getName().equals("dots")) {// dots
				for (Object temp : subnode.elements()) {
					Element subsubNode = (Element) temp;
					if (subsubNode.getName().equals("e")) {
						for (Object tempEle : subsubNode.elements()) {
							Element lastNode = (Element) tempEle;
							if (lastNode.getName().equals("x")) {
								loaction_dot_x = lastNode.getText();
							} else if (lastNode.getName().equals("y")) {
								location_dot_y = lastNode.getText();
							}
						}
						break;
					}
				}
			} else if (subnode.getName().equals("textPos")) {// textPos
				for (Object temp : subnode.elements()) {
					Element subsubNode = (Element) temp;
					if (subsubNode.getName().equals("x")) {
						location_x = subsubNode.getText();
					} else if (subsubNode.getName().equals("y")) {
						location_y = subsubNode.getText();
					}
				}
				String g = location_x + "," + location_y;
				if (!location_dot_y.equals("")) {
					g = loaction_dot_x + "," + location_dot_y + ":" + location_x + "," + location_y;
				}
				path.setG(g);
			} else if (subnode.getName().equals("text")) {
				for (Object temp : subnode.elements()) {
					Element subsubNode = (Element) temp;
					if (subsubNode.getName().equals("text")) {
						path.setName(subsubNode.getText());
						break;
					}
				}
			}
		}

		return path;
	}

	// 步骤
	private HashMap<String, List<WorkflowPath>> analysisPaths(Element node) {

		HashMap<String, List<WorkflowPath>> mapPaths = new HashMap<String, List<WorkflowPath>>();

		for (Object pathElement : node.elements()) {
			Element rect = (Element) pathElement;

			WorkflowPath path = analysisPath(rect);

			if (mapPaths.containsKey(path.getFrom())) {
				mapPaths.get(path.getFrom()).add(path);
			} else {
				List<WorkflowPath> pathList = new ArrayList<WorkflowPath>();
				pathList.add(path);
				mapPaths.put(path.getFrom(), pathList);
			}
		}

		return mapPaths;
	}

}
